#!/usr/bin/perl -w
use strict;
use App::Options (
    options => [qw(site verbose)],
    option => {
        site => {
            description => "The site to find the location of the debug.out file",
            default => 'dbfoundry.com',
        },
        verbose => {
            description => "verbose",
            default => 0,
        },
    },
);
use JSON;
{
    my ($url, $line, $server, $request, $request_headers, $options, $request_values, $response);
    my (@url, @server, @request, @request_headers, @options, @request_values, @response);
    my (@files);
    my $verbose = $App::options{verbose};
    my $active_requests            = 0;
    my $overlapping_requests       = 0;
    my $active_request_starts      = 0;
    my $overlapping_request_starts = 0;
    if ($#ARGV > -1) {
        @files = @ARGV;
    }
    else {
        @files = ("/www/$App::options{site}/env/dev/log/debug.out");
    }
    foreach my $file (@files) {
        open(my $fh, "<", $file) || die "Can't open file $file: $!";
        while (<$fh>) {
            if (/^# URL: (.*)/) {
                $url = $1;
                $active_requests++;
                $overlapping_requests = 1 if ($active_requests >= 2);
                $active_request_starts++;
                $overlapping_request_starts = 1 if ($active_request_starts >= 2);
                print $_ if ($verbose);
                push(@url, $url);
                print " > ", counts(\@url, \@server, \@request, \@request_headers, \@options, \@request_values, \@response), "\n" if ($verbose);
            }
            elsif (/^\$_SERVER/) {
                $server = slurp_json($fh);
                print " > SERVER = ", ref($server), "\n" if ($verbose);
                #print to_json($server, {pretty=>1});
                push(@server, $server);
                print " > ", counts(\@url, \@server, \@request, \@request_headers, \@options, \@request_values, \@response), "\n" if ($verbose);
            }
            elsif (/^\$_REQUEST/) {
                $request = slurp_json($fh);
                print " > REQUEST = ", ref($request), "\n" if ($verbose);
                #print to_json($request, {pretty=>1});
                push(@request, $request);
                print " > ", counts(\@url, \@server, \@request, \@request_headers, \@options, \@request_values, \@response), "\n" if ($verbose);
            }
            elsif (/^REQUEST-HEADERS/) {
                $request_headers = slurp_json($fh);
                print " > REQUEST-HEADERS = ", ref($request_headers), "\n" if ($verbose);
                #print to_json($request_headers, {pretty=>1});
                push(@request_headers, $request_headers);
                print " > ", counts(\@url, \@server, \@request, \@request_headers, \@options, \@request_values, \@response), "\n" if ($verbose);
            }
            elsif (/^# OPTIONS:/) {
                skip_lines($fh, 1);   # a comment line
                $options = slurp_json($fh);
                print " > OPTIONS = ", ref($options), "\n" if ($verbose);
                #print to_json($options, {pretty=>1});
                push(@options, $options);
                print " > ", counts(\@url, \@server, \@request, \@request_headers, \@options, \@request_values, \@response), "\n" if ($verbose);

                $active_request_starts--;
                $overlapping_request_starts = 0 if ($active_request_starts == 0);

                if ($url[0] !~ /api.php/) {
                    shift(@url);
                    shift(@server);
                    shift(@request);
                    shift(@request_headers);
                    shift(@options);
                    $active_requests--;
                    $overlapping_requests = 0 if ($active_requests == 0);
                }
            }
            elsif (/^PARSED$/) {
                $request_values = slurp_json($fh);
                print " > REQUEST-VALUES = ", ref($request_values), "\n" if ($verbose);
                #print to_json($request_values, {pretty=>1});
                push(@request_values, $request_values);
                print " > ", counts(\@url, \@server, \@request, \@request_headers, \@options, \@request_values, \@response), "\n" if ($verbose);
            }
            elsif (/SimpleRest->sendResponse()/) {
                #| +-SimpleRest->sendResponse() [defined in: SimpleRest] [called from: sitefront/front-framework/lib/SimpleRest.php(150)]
                #| +-> return({"nrows":1,"table":"tracked_url","key":"663","message":"Deleted 1 row","success":true})
                $line = <$fh>;
                chomp($line);
                $line =~ s/^[\| +>-]*return\(//;
                $line =~ s/\)$//;
                $response = from_json($line);
                print " > RESPONSE = ", ref($response), "\n" if ($verbose);
                #print to_json($response, {pretty=>1});
                push(@response, $response);
                print " > ", counts(\@url, \@server, \@request, \@request_headers, \@options, \@request_values, \@response), "\n" if ($verbose);

                if (!$overlapping_requests) {
                    create_test_case(pop(@url), pop(@server), pop(@request), pop(@request_headers), pop(@options), pop(@request_values), pop(@response), $overlapping_requests);
                }
                else {
                    pop(@url); pop(@server); pop(@request); pop(@request_headers); pop(@options); pop(@request_values); pop(@response);
                }
                print " > ", counts(\@url, \@server, \@request, \@request_headers, \@options, \@request_values, \@response), " : SHIFT (create_test_case)\n" if ($verbose);
                $active_requests--;
                $overlapping_requests = 0 if ($active_requests == 0);
            }
        }
        close($fh);
    }
}

#       $request  = array('db_name'=>'testdb');
#       $response = array();
#       $this->_callWebService ('GET', '/service/databaseAdmin/createDatabase', $request, $response);
#       # $response = { "success": true }
#       $this->assertTrue(isset($response['success']),                  "listDatabaseObjects: success");
#
#       $response = array();
#       $this->_callWebService ('GET', '/service/databaseAdmin/createDatabase', $request, $response);
#       # $response = {
#       #     "success": false,
#       #     "code": 0,
#       #     "message": "There is already a database by the name of 'testdb'",
#       # }
#       $this->assertFalse(isset($response['success']),                  "listDatabaseObjects: not success");
#       $this->assertTrue(isset($response['message']),                   "listDatabaseObjects: message is set");
#       $this->assertTrue(strpos($response['message']),                   "listDatabaseObjects: message is set");


sub create_test_case {
    my ($url, $server, $request, $request_headers, $options, $request_values, $response, $overlapping_requests) = @_;
    if (!$url || !ref($server) || !ref($request) || !ref($request_headers) || !ref($options) || !ref($request_values) || !ref($response)) {
        print "URL: [$url]\n";
        if (ref($server))          { print "SERVER\n",          to_json($server, {pretty=>1}); }          else { print "SERVER: [$server] SCALAR!\n"; }
        if (ref($request))         { print "REQUEST\n",         to_json($request, {pretty=>1}); }         else { print "REQUEST: [$request] SCALAR!\n"; }
        if (ref($request_headers)) { print "REQUEST_HEADERS\n", to_json($request_headers, {pretty=>1}); } else { print "REQUEST_HEADERS: [$request_headers] SCALAR!\n"; }
        if (ref($options))         { print "OPTIONS\n",         to_json($options, {pretty=>1}); }         else { print "OPTIONS: [$options] SCALAR!\n"; }
        if (ref($request_values))  { print "REQUEST_VALUES\n",  to_json($request_values, {pretty=>1}); }  else { print "REQUEST_VALUES: [$request_values] SCALAR!\n"; }
        if (ref($response))        { print "RESPONSE\n",        to_json($response, {pretty=>1}); }        else { print "RESPONSE: [$response] SCALAR!\n"; }
        exit(1);
    }

    if ($App::options{verbose}) {
        print "SERVER\n",          to_json($server, {pretty=>1});
        print "REQUEST_VALUES\n",  to_json($request_values, {pretty=>1});
        print "RESPONSE\n",        to_json($response, {pretty=>1});
    }

    my $http_method   = $server->{REQUEST_METHOD};
    my $script_name   = $server->{SCRIPT_NAME};
    my ($service, $rows, $value, $ref);
    if ($script_name  =~ /api.php$/ && $server->{PATH_INFO}) {
        $service      = $server->{PATH_INFO};
    }
    else {
        $service      = $script_name;
        $service      =~ s!.*/apps/!!;
    }
    my $service_short = $service;
    $service_short =~ s!.*/([a-z])!$1!;
    if ($request_values->{data} && ref($request_values->{data}) eq "ARRAY" && $#{$request_values->{data}} > 1) {
        $rows = [ $request_values->{data}[0], $request_values->{data}[1] ];
        $request_values->{data} = $rows;
    }
    if ($response->{data} && ref($response->{data}) eq "ARRAY" && $#{$response->{data}} > 1) {
        $rows = [ $response->{data}[0], $response->{data}[1] ];
        $response->{data} = $rows;
    }
    my $warning = $overlapping_requests ? " (test case may be corrupted due to overlapping requests in the log file)" : "";
    print "        #########################################################################\n";
    print "        # TEST: $http_method $service$warning\n";
    print "        #########################################################################\n";
    print "        \$request_json = <<<EOF\n";
    print to_json($request_values, {pretty=>1});
    print "EOF;\n";
    print "        \$request  = json_decode(\$request_json, true);\n";
    print "        \$response = array();\n";
    print "        \$this->_callWebService('$http_method', '$service', \$request, \$response);\n";
    print "        \$expected_response_json = <<<EOF\n";
    print to_json($response, {pretty=>1});
    print "EOF;\n";
    print "        \$expected_response  = json_decode(\$expected_response_json, true);\n";
    print "        \$this->assertDeeply(\$expected_response, \$response, '$http_method $service_short response');\n";
    print "\n";
}

sub counts {
    my ($urls, $servers, $requests, $request_headerss, $optionss, $request_valuess, $responses) = @_;
    "[".($#$urls+1).",".($#$servers+1).",".($#$requests+1).",".($#$request_headerss+1).",".($#$optionss+1).",".($#$request_valuess+1).",".($#$responses+1)."]";
}

# skip_lines($fh, 1);   # a comment line
sub skip_lines {
    my ($fh, $count) = @_;
    for (my $i = 0; $i < $count; $i++) {
        <$fh>;
    }
}

sub slurp_json {
    my ($fh) = @_;
    my $json = "";
    my ($line);
    while (1) {
        $line = <$fh>;
        last if (!defined $line);
        $json .= $line;
        last if ($line =~ /^[\]\}]$/);
    }
    my $struct = from_json($json);
    if (ref($struct) eq "ARRAY" && $#$struct == -1) {
        $struct = {};
    }
    return($struct);
}

__END__

SERVER
   "SCRIPT_NAME" : "/v/dev/apps/sitefront/front-framework/api.php",
   "PATH_INFO" : "/object/app/tracked_url",
   "REQUEST_METHOD" : "GET",
   "HTTP_ACCEPT" : "*/*",
   "SCRIPT_FILENAME" : "/mnt/id/apache/acoexhibithall.com/htdocs/v/dev/apps/sitefront/front-framework/api.php",
   "REQUEST_SCHEME" : "http",
   "REQUEST_TIME_FLOAT" : 1392331282.531,
   "SERVER_SOFTWARE" : "Apache/2.4.6 (Ubuntu)",
   "QUERY_STRING" : "_dc=1392331374384&page=1&start=0&limit=100",
   "REMOTE_PORT" : "53418",
   "HTTP_USER_AGENT" : "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.22 (KHTML, like Gecko) Ubuntu Chromium/25.0.1364.160 Chrome/25.0.1364.160 Safari/537.22",
   "SERVER_SIGNATURE" : "<address>Apache/2.4.6 (Ubuntu) Server at www.acoexhibithall.com Port 80</address>\n",
   "HTTP_ACCEPT_LANGUAGE" : "en-US,en;q=0.8",
   "PATH" : "/usr/local/bin:/usr/bin:/bin",
   "GATEWAY_INTERFACE" : "CGI/1.1",
   "DOCUMENT_ROOT" : "/mnt/id/apache/acoexhibithall.com/htdocs",
   "HTTP_X_REQUESTED_WITH" : "XMLHttpRequest",
   "PATH_TRANSLATED" : "/mnt/id/apache/acoexhibithall.com/htdocs/object/app/tracked_url",
   "SERVER_NAME" : "www.acoexhibithall.com",
   "PROTOSSL" : "",
   "HTTP_REFERER" : "http://www.acoexhibithall.com/v/dev/apps/acoexhibithall/website/admin/",
   "HTTP_ACCEPT_ENCODING" : "gzip,deflate,sdch",
   "SERVER_ADMIN" : "webmaster@internetdynamics.com",
   "HTTP_CONNECTION" : "keep-alive",
   "CONTEXT_PREFIX" : "",
   "REQUEST_TIME" : 1392331282,
   "HTTP_ACCEPT_CHARSET" : "ISO-8859-1,utf-8;q=0.7,*;q=0.3",
   "SERVER_PORT" : "80",
   "HTTP_COOKIE" : "ff-session=%7B%22user_token%22%3A%22guest%22%2C%22auth_token%22%3A%22xxxxxx%22%2C%22session_expire_dttm%22%3A%222038-01-01+00%3A00%3A00%22%2C%22group_id%22%3A%221%22%2C%22app_id%22%3A%221%22%7D; ff-meta-session=564; ff-meta-session-dev=10; ff-session-dev=%7B%22user_token%22%3A%22guest%22%2C%22auth_token%22%3A%22xxxxxx%22%2C%22session_expire_dttm%22%3A%222038-01-01+00%3A00%3A00%22%2C%22group_id%22%3A%221%22%2C%22app_id%22%3A%221%22%7D",
   "REMOTE_ADDR" : "184.47.52.238",
   "CONTEXT_DOCUMENT_ROOT" : "/mnt/id/apache/acoexhibithall.com/htdocs",
   "SERVER_PROTOCOL" : "HTTP/1.1",
   "REQUEST_URI" : "/v/dev/apps/sitefront/front-framework/api.php/object/app/tracked_url?_dc=1392331374384&page=1&start=0&limit=100",
   "SERVER_ADDR" : "10.99.46.98",
   "PHP_SELF" : "/v/dev/apps/sitefront/front-framework/api.php/object/app/tracked_url",
   "HTTP_HOST" : "www.acoexhibithall.com"

